﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;
using BLevy.Datos.Interfases;
using BLevy.Entidad;
using System.Data;
using MySql.Data.MySqlClient;
using System.Configuration;

namespace BLevy.Datos.Repositories
{
    public interface ICobroRepository : IRepository<Cobro>
    {
        int RegistrarCobro(Cobro _cobro);
        int RegistrarCobroCobrador(CobradorCobro cobrador_cobro);
        IList<Cobro> FindAllCobrosPorAfiliado(int socio_id);
        IList<Cobro> FindAllFiltro(string numero_cupon, int? formapago_id, DateTime? desde, DateTime? hasta);
        Cobro FindByIdCupon(int cupon_id);
        Cobro FindLastCobroPorAfiliado(int socio_id);
        int DebitosRechazados(DebitoRechazado debitos);
        IList<DebitoRechazado> FindAllDebitosRechazadosFiltro(string numerocupon, DateTime? desde, DateTime? hasta);
        IList<DebitoRechazado> FindDebitosRechazadosPorFecha(DateTime fecha);
    }

    public class CobroRepository : ICobroRepository
    {
        protected readonly IDbConnection _db;

        public CobroRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        //public int RegistrarCobro(string nroCupon)
        //{
        //    Datos.Repositories.PeriodoRepository periodoRepository = new PeriodoRepository();

        //    int resultado = 0;
        //    int resultadoCupon = 0;
        //    bool res = true;
        //    string query = "INSERT INTO COBROS (CUPON_ID, FORMAPAGO_ID, FECHA, TOTAL) " +
        //                    " VALUES (@cupon_id, @formapago_id, @fecha, @total)";

        //    //string queryCobradorCupon = "UPDATE CUPONES SET TRANSITO = @transito WHERE ID = @cupon_id";

        //    string queryCupon = "UPDATE CUPONES SET ESTADO = @estado, TRANSITO = @transito WHERE ID = @cupon_id";



        //    using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
        //    {
        //        _db.Open();
        //        using (var tran = _db.BeginTransaction())
        //        {
        //            try
        //            {
        //                foreach (var c in cobradoresCuponesL)
        //                {
        //                    double total = 0;
        //                    IList<Periodo> periodo = periodoRepository.GetPeriodosByIdCupon(c.cupon.id);

        //                    total = c.cupon.total;

        //                    if (c.fecha >= periodo[0].vencimiento_2)
        //                    {
        //                        total += periodo[0].recargo;
        //                    }

        //                    resultado = _db.Execute(query, new
        //                    {
        //                        cupon_id = c.cupon_id,
        //                        formapago_id = 1,
        //                        fecha = c.fecha,
        //                        total = total
        //                    });

        //                    if (resultado == 0)
        //                    {
        //                        res = false;
        //                        break;
        //                    }
        //                    else
        //                    {
        //                        resultadoCupon = _db.Execute(queryCupon, new
        //                        {
        //                            estado = "P",
        //                            transito = "I",
        //                            cupon_id = c.cupon_id
        //                        });

        //                        if (resultadoCupon == 0)
        //                        {
        //                            res = false;
        //                            break;
        //                        }
        //                    }
        //                }

        //                if (res == true)
        //                {
        //                    tran.Commit();
        //                }
        //                else
        //                {
        //                    tran.Rollback();
        //                    resultado = 0;
        //                }

        //                return resultado;
        //            }
        //            catch
        //            {
        //                tran.Rollback();
        //                resultado = 0;

        //                return resultado;
        //            }
        //        }
        //    }
        //}

        public IList<Cobro> FindAll()
        {
            string query = "SELECT * FROM COBROS " +
                "INNER JOIN FORMASPAGO ON FORMASPAGO.ID = COBROS.FORMAPAGO_ID " +
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "ORDER BY COBROS.FECHA DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro, FormaPago, Cupon, Cobro>(query,
                        (cobro, formapago, cupon) =>
                        {
                            cobro.formapago = formapago;
                            cobro.cupon = cupon;
                            return cobro;
                        }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Cobro> Find(System.Linq.Expressions.Expression<Func<Cobro, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Cobro FindById(int id)
        {
            const string query = "SELECT * FROM COBROS " +
                "WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int Add(Cobro newEntity)
        {
            throw new NotImplementedException();
        }

        public int Remove(int id)
        {
            throw new NotImplementedException();
        }

        public int Modify(Cobro entity)
        {
            throw new NotImplementedException();
        }

        public int RegistrarCobro(Cobro _cobro)
        {
            string query = "INSERT INTO COBROS (CUPON_ID, FORMAPAGO_ID, FECHA, TOTAL) " +
                        " VALUES (@cupon_id, @formapago_id, @fecha, @total);" +
                        "SELECT LAST_INSERT_ID();";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {

                    //inserto el cupon
                    return _db.Query<int>(query, new
                    {
                        cupon_id = _cobro.cupon_id,
                        formapago_id = _cobro.formapago_id,
                        fecha = _cobro.fecha,
                        total = _cobro.total
                    }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public int RegistrarCobroCobrador(CobradorCobro cobrador_cobro)
        {
            const string query = "INSERT INTO COBRADORESCOBROS (COBRADOR_ID, COBRO_ID, COBRADORCUPON_ID, FECHA_COBRO, COMISION, ESTADO) " +
                "VALUES (@cobrador_id, @cobro_id, @cobradorcupon_id, @fecha_cobro, @comision, @estado)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        cobrador_id = cobrador_cobro.cobrador_id,
                        cobro_id = cobrador_cobro.cobro_id,
                        cobradorcupon_id = cobrador_cobro.cobradorcupon_id,
                        fecha_cobro = cobrador_cobro.fecha_cobro,
                        comision = cobrador_cobro.comision,
                        estado = cobrador_cobro.estado
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<Cobro> FindAllCobrosPorAfiliado(int socio_id)
        {
            const string query = "SELECT * FROM COBROS " +
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "WHERE CUPONES.SOCIO_ID = @socio_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro, Cupon, Cobro>(query,
                        (cobro, cupon) =>
                        {
                            cobro.cupon = cupon;
                            return cobro;
                        }, new
                        {
                            socio_id = socio_id
                        }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public IList<Cobro> FindAllFiltro(string numero_cupon, int? formapago_id, DateTime? desde, DateTime? hasta)
        {

            string query = "SELECT * FROM COBROS " +
                "INNER JOIN FORMASPAGO ON FORMASPAGO.ID = COBROS.FORMAPAGO_ID " +
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "WHERE ((CUPONES.NUMERO LIKE @numero_cupon) OR (@numero_cupon IS NULL)) " +
                "AND ((COBROS.FORMAPAGO_ID = @formapago_id) OR (@formapago_id IS NULL)) " +
                "AND ((COBROS.FECHA BETWEEN @desde AND @hasta) OR ((@desde IS NULL) OR (@hasta IS NULL))) " +
                "ORDER BY COBROS.FECHA DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro, FormaPago, Cupon, Cobro>(query,
                        (cobro, formapago, cupon) =>
                        {
                            cobro.formapago = formapago;
                            cobro.cupon = cupon;
                            return cobro;
                        }, new { 
                            numero_cupon = numero_cupon, 
                            formapago_id = formapago_id, 
                            desde = desde, 
                            hasta = hasta }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public Cobro FindByIdCupon(int cupon_id)
        {
            string query = "SELECT * FROM COBROS " +
                "WHERE CUPON_ID = @cupon_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro>(query, new { cupon_id = cupon_id }).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public Cobro FindLastCobroPorAfiliado(int socio_id)
        {
            const string query = "SELECT C.* FROM COBROS C " +
                "INNER JOIN CUPONES P ON P.ID = C.CUPON_ID " +
                "WHERE P.SOCIO_ID = @socio_id " +
                "ORDER BY id DESC " +
                "LIMIT 1";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cobro>(query, new { socio_id = socio_id }).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public int DebitosRechazados(DebitoRechazado debito)
        {
            string query = "INSERT INTO DEBITOSRECHAZADOS (CUPON_ID, FECHA, ERROR, OBSERVACION) " +
                "VALUES (@cupon_id, @fecha, @error, @observacion)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        cupon_id = debito.cupon_id,
                        fecha = debito.fecha,
                        error = debito.error,
                        observacion = debito.observacion
                    });
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public IList<DebitoRechazado> FindAllDebitosRechazadosFiltro(string numerocupon, DateTime? desde, DateTime? hasta)
        {
            string query = "SELECT * FROM DEBITOSRECHAZADOS " +
                "INNER JOIN CUPONES ON CUPONES.ID = DEBITOSRECHAZADOS.CUPON_ID " +
                "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
                "WHERE ((CUPONES.NUMERO LIKE CONCAT('%', @numerocupon, '%')) OR (@numerocupon IS NULL)) " +
                "AND ((DEBITOSRECHAZADOS.FECHA BETWEEN @desde AND @hasta) OR ((@desde IS NULL) OR (@hasta IS NULL))) " +
                "ORDER BY DEBITOSRECHAZADOS.FECHA DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<DebitoRechazado, Cupon, Socio, DebitoRechazado>(query,
                        (debito, cupon, socio) =>
                        {
                            debito.cupon = cupon;
                            debito.cupon.socio = socio;
                            return debito;
                        }, new 
                        { 
                            numerocupon = numerocupon, 
                            desde = desde, 
                            hasta = hasta
                        }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public IList<DebitoRechazado> FindDebitosRechazadosPorFecha(DateTime fecha)
        {
            string query = "SELECT * FROM DEBITOSRECHAZADOS " +
                "INNER JOIN CUPONES ON CUPONES.ID = DEBITOSRECHAZADOS.CUPON_ID " +
                "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
                "WHERE DEBITOSRECHAZADOS.FECHA BETWEEN @fecha AND @fecha";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<DebitoRechazado, Cupon, Socio, DebitoRechazado>(query,
                        (debito, cupon, socio) =>
                        {
                            debito.cupon = cupon;
                            debito.cupon.socio = socio;
                            return debito;
                        }, new
                        {
                            fecha = fecha

                        }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


    }
}